import React, { useRef, useEffect, useState, useCallback } from 'react';
import TileLoader from '../utils/tileLoader';

const MapRenderer = ({ 
  center = [0, 0], 
  zoom = 0, 
  showTiles = true, 
  showVectors = true,
  onViewChange 
}) => {
  const canvasRef = useRef(null);
  const tileLoaderRef = useRef(new TileLoader());
  const animationRef = useRef(null);
  
  const [viewState, setViewState] = useState({
    center: center,
    zoom: zoom,
    panning: false,
    lastMousePos: null
  });

  // 计算瓦片坐标
  const getTileCoordinates = useCallback((lon, lat, zoom) => {
    const latRad = lat * Math.PI / 180;
    const n = Math.pow(2, zoom);
    const x = Math.floor((lon + 180) / 360 * n);
    const y = Math.floor((1 - Math.asinh(Math.tan(latRad)) / Math.PI) / 2 * n);
    return { x, y };
  }, []);

  // 计算可见瓦片范围
  const getVisibleTiles = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return [];

    const { width, height } = canvas;
    const zoom = viewState.zoom;
    const centerTile = getTileCoordinates(viewState.center[0], viewState.center[1], zoom);
    
    const tilesPerScreen = Math.max(1, Math.ceil(Math.max(width, height) / 256));
    const visibleTiles = [];

    for (let dx = -tilesPerScreen; dx <= tilesPerScreen; dx++) {
      for (let dy = -tilesPerScreen; dy <= tilesPerScreen; dy++) {
        const x = centerTile.x + dx;
        const y = centerTile.y + dy;
        
        if (x >= 0 && x < Math.pow(2, zoom) && y >= 0 && y < Math.pow(2, zoom)) {
          visibleTiles.push({ z: zoom, x, y });
        }
      }
    }

    return visibleTiles;
  }, [viewState.center, viewState.zoom, getTileCoordinates]);

  // 渲染地图
  const renderMap = useCallback(async () => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    const { width, height } = canvas;

    // 清除画布
    ctx.clearRect(0, 0, width, height);

    // 绘制背景
    ctx.fillStyle = '#2d3748';
    ctx.fillRect(0, 0, width, height);

    const visibleTiles = getVisibleTiles();
    
    // 预加载瓦片
    tileLoaderRef.current.preloadTiles(visibleTiles);

    // 渲染瓦片
    if (showTiles) {
      for (const tile of visibleTiles) {
        const { z, x, y } = tile;
        
        try {
          const imageUrl = await tileLoaderRef.current.loadTileImage(z, x, y);
          if (imageUrl) {
            const img = new Image();
            img.onload = () => {
              // 计算瓦片在画布上的位置
              const tileSize = 256 * Math.pow(2, viewState.zoom - z);
              const centerTile = getTileCoordinates(viewState.center[0], viewState.center[1], z);
              const offsetX = (x - centerTile.x) * tileSize + width / 2;
              const offsetY = (y - centerTile.y) * tileSize + height / 2;

              ctx.drawImage(img, offsetX, offsetY, tileSize, tileSize);
            };
            img.src = imageUrl;
          }
        } catch (error) {
          console.warn(`Failed to render tile z=${z}, x=${x}, y=${y}:`, error);
        }
      }
    }

    // 渲染矢量数据
    if (showVectors) {
      for (const tile of visibleTiles) {
        const { z, x, y } = tile;
        
        try {
          const vectorData = await tileLoaderRef.current.loadVectorData(z, x, y);
          if (vectorData && vectorData.features) {
            // 计算瓦片在屏幕上的位置
            const tileSize = 256 * Math.pow(2, viewState.zoom - z);
            const centerTile = getTileCoordinates(viewState.center[0], viewState.center[1], z);
            
            // 计算瓦片相对于中心瓦片的偏移
            const offsetX = (x - centerTile.x) * tileSize + width / 2;
            const offsetY = (y - centerTile.y) * tileSize + height / 2;

            // 绘制矢量要素
            vectorData.features.forEach(feature => {
              if (feature.geometry) {
                ctx.save();
                ctx.translate(offsetX, offsetY);
                
                // 根据当前缩放级别调整线宽和样式
                const baseLineWidth = 2;
                const minLineWidth = 0.5;
                const maxLineWidth = 4;
                
                // 动态调整线宽，在缩放时保持视觉一致性
                const lineWidth = Math.max(minLineWidth, Math.min(maxLineWidth, baseLineWidth / Math.pow(2, viewState.zoom - 5)));
                
                // 设置样式
                ctx.strokeStyle = '#4299e1';
                ctx.fillStyle = 'rgba(66, 153, 225, 0.1)';
                ctx.lineWidth = lineWidth;
                ctx.lineJoin = 'round';
                ctx.lineCap = 'round';

                // 绘制几何图形（使用正确的缩放比例和瓦片级别）
                drawGeometry(ctx, feature.geometry, Math.pow(2, viewState.zoom - z), z);
                
                ctx.restore();
              }
            });
          }
        } catch (error) {
          console.warn(`Failed to render vector data z=${z}, x=${x}, y=${y}:`, error);
        }
      }
    }

    // 绘制网格线（调试用）
    if (process.env.NODE_ENV === 'development') {
      ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
      ctx.lineWidth = 1;
      
      // 绘制经纬度网格
      const gridSize = 50;
      for (let x = 0; x <= width; x += gridSize) {
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, height);
        ctx.stroke();
      }
      
      for (let y = 0; y <= height; y += gridSize) {
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(width, y);
        ctx.stroke();
      }
    }

  }, [viewState, showTiles, showVectors, getVisibleTiles, getTileCoordinates]);

  // 将经纬度坐标转换为瓦片像素坐标
  const lonLatToTilePixel = (lon, lat, z) => {
    // 将经纬度转换为瓦片坐标
    const latRad = lat * Math.PI / 180;
    const n = Math.pow(2, z);
    const tileX = ((lon + 180) / 360) * n;
    const tileY = ((1 - Math.asinh(Math.tan(latRad)) / Math.PI) / 2) * n;
    
    // 转换为瓦片内的像素坐标（0-256）
    const pixelX = (tileX - Math.floor(tileX)) * 256;
    const pixelY = (tileY - Math.floor(tileY)) * 256;
    
    return { pixelX, pixelY };
  };

  // 绘制几何图形
  const drawGeometry = (ctx, geometry, scale = 1, z = 0) => {
    if (geometry.type === 'LineString' && geometry.coordinates) {
      ctx.beginPath();
      geometry.coordinates.forEach((coord, index) => {
        const [lon, lat] = coord;
        const { pixelX, pixelY } = lonLatToTilePixel(lon, lat, z);
        const scaledX = pixelX * scale;
        const scaledY = pixelY * scale;
        if (index === 0) {
          ctx.moveTo(scaledX, scaledY);
        } else {
          ctx.lineTo(scaledX, scaledY);
        }
      });
      ctx.stroke();
    } else if (geometry.type === 'Polygon' && geometry.coordinates) {
      geometry.coordinates.forEach(ring => {
        ctx.beginPath();
        ring.forEach((coord, index) => {
          const [lon, lat] = coord;
          const { pixelX, pixelY } = lonLatToTilePixel(lon, lat, z);
          const scaledX = pixelX * scale;
          const scaledY = pixelY * scale;
          if (index === 0) {
            ctx.moveTo(scaledX, scaledY);
          } else {
            ctx.lineTo(scaledX, scaledY);
          }
        });
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
      });
    }
  };

  // 处理鼠标事件
  const handleMouseDown = (e) => {
    setViewState(prev => ({
      ...prev,
      panning: true,
      lastMousePos: { x: e.clientX, y: e.clientY }
    }));
  };

  const handleMouseMove = (e) => {
    if (!viewState.panning || !viewState.lastMousePos) return;

    const deltaX = e.clientX - viewState.lastMousePos.x;
    const deltaY = e.clientY - viewState.lastMousePos.y;

    // 计算新的中心点（使用更精确的投影计算）
    const canvas = canvasRef.current;
    if (!canvas) return;
    
    const { width, height } = canvas;
    const scale = Math.pow(2, viewState.zoom);
    
    // 使用更精确的经纬度转换，考虑屏幕像素到地理坐标的映射
    const deltaLon = (deltaX / width) * 360 / scale;
    const deltaLat = -(deltaY / height) * 180 / scale;

    const newCenter = [
      viewState.center[0] - deltaLon,
      Math.max(-85, Math.min(85, viewState.center[1] - deltaLat))
    ];

    setViewState(prev => ({
      ...prev,
      center: newCenter,
      lastMousePos: { x: e.clientX, y: e.clientY }
    }));

    onViewChange?.(newCenter, viewState.zoom);
  };

  const handleMouseUp = () => {
    setViewState(prev => ({
      ...prev,
      panning: false,
      lastMousePos: null
    }));
  };

  const handleWheel = (e) => {
    e.preventDefault();
    
    // 计算缩放增量，考虑滚轮速度
    const delta = -Math.sign(e.deltaY) * 0.2;
    const newZoom = Math.max(0, Math.min(10, viewState.zoom + delta));
    
    if (newZoom !== viewState.zoom) {
      // 计算缩放中心点（鼠标位置）
      const canvas = canvasRef.current;
      if (!canvas) return;
      
      const rect = canvas.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;
      
      // 计算缩放后的新中心点，实现以鼠标为中心的缩放
      const { width, height } = canvas;
      const scaleFactor = Math.pow(2, newZoom - viewState.zoom);
      
      const relativeX = mouseX - width / 2;
      const relativeY = mouseY - height / 2;
      
      const newCenterX = viewState.center[0] - (relativeX / width) * 360 / Math.pow(2, viewState.zoom) * (1 - 1/scaleFactor);
      const newCenterY = viewState.center[1] + (relativeY / height) * 180 / Math.pow(2, viewState.zoom) * (1 - 1/scaleFactor);
      
      const newCenter = [
        newCenterX,
        Math.max(-85, Math.min(85, newCenterY))
      ];
      
      setViewState(prev => ({
        ...prev,
        center: newCenter,
        zoom: newZoom
      }));
      
      onViewChange?.(newCenter, newZoom);
    }
  };

  // 调整画布大小
  const resizeCanvas = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const container = canvas.parentElement;
    if (!container) return;

    const { width, height } = container.getBoundingClientRect();
    
    if (canvas.width !== width || canvas.height !== height) {
      canvas.width = width;
      canvas.height = height;
    }
  }, []);

  // 动画循环
  useEffect(() => {
    const animate = () => {
      renderMap();
      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);
    
    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [renderMap]);

  // 窗口大小变化监听
  useEffect(() => {
    resizeCanvas();
    
    const handleResize = () => {
      resizeCanvas();
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [resizeCanvas]);

  // 清理资源
  useEffect(() => {
    return () => {
      tileLoaderRef.current.clearCache();
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      className="map-canvas"
      onMouseDown={handleMouseDown}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
      onMouseLeave={handleMouseUp}
      onWheel={handleWheel}
      style={{
        cursor: viewState.panning ? 'grabbing' : 'grab'
      }}
    />
  );
};

export default MapRenderer;